package com.atXiao.video.service.impl;

import com.atXiao.video.common.entity.ResBody;
import com.atXiao.video.common.rspEnum.BaseRespEnum;
import com.atXiao.video.common.rspEnum.BusinessEnum;
import com.atXiao.video.common.rspEnum.RedisKeyEnum;
import com.atXiao.video.entity.Subscribe;
import com.atXiao.video.entity.User;
import com.atXiao.video.entity.req.common.MessageDto;
import com.atXiao.video.entity.req.subscribe.SubscribeReq;
import com.atXiao.video.entity.resp.notify.NotifyResp;
import com.atXiao.video.mapper.SubscribeMapper;
import com.atXiao.video.service.SubscribeService;
import com.atXiao.video.service.UserService;
import com.atXiao.video.utils.RedisUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import org.springframework.util.ObjectUtils;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.UUID;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author lixiaoxiao
 * @since 2021-03-17
 */
@Service
@RefreshScope
public class SubscribeServiceImpl extends ServiceImpl<SubscribeMapper, Subscribe> implements SubscribeService {

    private final static Logger logger = LoggerFactory.getLogger(SubscribeServiceImpl.class);


    @Autowired
    UserService userService;

    /**
     * 专门用来维护用户发布订阅相关的消息
     */
    @Value("${user.subscribeChannel}")
    private String subscribeChannel;


    @Autowired
    RedisUtils redisUtils;


    @Override
    public ResBody followerUser(SubscribeReq subscribeReq) {
        ResBody resBody = new ResBody();
        //当前用户编号
        String yourId = subscribeReq.getYoutuber();
        //要去订阅的用户编号
        String subscriberId = subscribeReq.getSubscriber();
        //TODO 1、校验要订阅的用户是否为公开用户
        User youtube = userService.getById(yourId);
        User subscriber = userService.getById(subscriberId);
        if (ObjectUtils.isEmpty(youtube) || ObjectUtils.isEmpty(subscriber)) {
            return ResBody.error(BaseRespEnum.LOGIN_WITHOUT_USER.getCode(), BaseRespEnum.LOGIN_WITHOUT_USER.getMsg());
        }
        //用户为私密用户
        if (BusinessEnum.private_user.getCode().equals(subscriber.getStatus())) {
            return ResBody.error(BaseRespEnum.CANT_SUBSCRIBE.getCode(), BaseRespEnum.CANT_SUBSCRIBE.getMsg());
        }
        //TODO 2、校验是否存在过绑定关系
        HashMap<String, Object> paraMap = new HashMap<>();
        paraMap.put("youtuber", yourId);
        paraMap.put("subscriber", subscriberId);
        //订阅列表
        List<Subscribe> subscribeList = this.getBaseMapper().selectByMap(paraMap);
        if (!CollectionUtils.isEmpty(subscribeList)) {
            return ResBody.error(BaseRespEnum.SUBLIST_NOT_NULL.getCode(), BaseRespEnum.SUBLIST_NOT_NULL.getMsg());
        }

        //TODO 3、存储绑定关系
        Subscribe subscribeRelation = new Subscribe();
        //你的ID
        subscribeRelation.setYoutuber(yourId);
        //关注的人的ID
        subscribeRelation.setSubscriber(subscriberId);
        //关注时间
        subscribeRelation.setSubscribe_time(new Date());
        this.save(subscribeRelation);


        //消息传输实体
        MessageDto messageDto = new MessageDto();
        //流水号
        String trace = UUID.randomUUID().toString();
        String title = "订阅消息";
        //消息主题
        messageDto.setTitle(title);
        //组装的消息内容
        String messageContext = subscribeReq.getYoutuber() + "," + subscribeReq.getSubscriber();
        messageDto.setTrace(trace);
        messageDto.setContent(messageContext);
        logger.info("存储订阅关系成功");
        //TODO redis发布消息
        redisUtils.convertAndSend(subscribeChannel, messageDto);
        logger.info("用户订阅消息发送成功，流水号为{},消息主题为{},消息内容为{}", trace, title, messageContext);
        return resBody;
    }


    @Override
    public NotifyResp getNotifyMsg(String youtuber) {
        NotifyResp notifyResp = new NotifyResp();
        //直接从缓存中获取列表集合
        List<Object> notifyMsgs = redisUtils.lGet(RedisKeyEnum.user_sub_prefix.getKeyPrefix() + youtuber, 0, -1);
        notifyResp.setNotifyMsgs(notifyMsgs);
        //通知的消息条数
        int notifyCount = notifyMsgs.size();
        //消息大于99条展示99+，否则直接展示消息的数量
        notifyResp.setCount(notifyCount > 99 ? "99+" : notifyCount + "");
        return notifyResp;
    }






    @Override
    public void clearNotifyMsg(String youtuber) {
        redisUtils.del(RedisKeyEnum.user_sub_prefix.getKeyPrefix() + youtuber);
    }
}
